Item = Item or class({}, nil, Entity)

ItemComponentsList = require("components/item/require")
ItemStateList = require("items/require")

function Item:constructor(itemName, position)
	getbase(Item).constructor(self)

	self.components = {}

	if itemName then
		self:SetItem(CreateItem(itemName, nil, nil))
	end

	if self:GetItem() and position then
		local container = CreateItemOnPositionSync(position, self:GetItem())
	end
end

function Item:AddComponent(componentName)
	local component = ItemComponentsList[componentName]
	if component == nil then
		return self
	end

	if component.Activate then
		component.Activate(self)
	end

	for key, value in pairs(component) do
		if key ~= "Activate" then
			if self[key] ~= nil then
				print("Warning! Colliding key", key)
			end

			self[key] = value
		end
	end

	self.components[componentName] = true

	return self
end

function Item:HasComponent(componentName)
	return self.components[componentName] ~= nil
end

function Item:SetItem(item)
	self.item = item

	self.item.GetParentEntity = function(item)
		return self
	end

	self:LoadItemState()
end

function Item:GetItem()
	return self.item
end

function Item:GetName()
	return self:GetItem():GetName()
end

function Item:IsStackable()
	return self:HasComponent("stackable")
end

function Item:IsEquipment()
	return self:HasComponent("equipment")
end

function Item:IsFiniteUses()
	return self:HasComponent("finite_uses")
end

function Item:IsPerishable()
	return self:HasComponent("perishable")
end


function Item:PutIntoContainer(itemContainer)
	self.container = itemContainer

	if itemContainer ~= nil then
		self:SetNetTable("container", self.container:GetIndex())
	else
		self:SetNetTable("container", nil)
	end
end

function Item:LoadItemState()
	local itemState = ItemStateList[self:GetName()]
	if itemState == nil then
		return
	end
	itemState.Load(self)
end

function Item:SetNetTable(key, value)
	self.nettable = self.nettable or {}

	self.nettable[key] = value
	self:UpdateNetTable()
end

function Item:GetNetTable(key)
	self.nettable = self.nettable or {}

	return self.nettable[key]
end

function Item:UpdateNetTable()
	self.nettable = self.nettable or {}

	CustomNetTables:SetTableValue("items", tostring(self:GetItem():entindex()), self.nettable)
end

function Item:Remove()
	if self.perishContextName ~= nil then
		GameRules:GetGameModeEntity():SetContextThink(self.perishContextName, nil, 0)
	end
	if self.container ~= nil then
		self.container:SetItemInSlot(nil, self.container:GetSlotByItem(self))
	end

	self.nettable = nil
	CustomNetTables:SetTableValue("items", tostring(self:GetItem():entindex()), nil)

	if self:GetItem():GetContainer() ~= nil then
		self:GetItem():GetContainer():RemoveSelf()
	end
	self:GetItem():RemoveSelf()

	getbase(Item).Remove(self)
end